package com.lb.uts.service.manager;

import com.lb.uts.constants.UTSConstants;
import com.lb.uts.entity.ScheduleJob;
import com.lb.uts.quartz.RscJob;
import com.lb.uts.service.IScheduleJobService;
import com.lb.uts.util.PolicyUtil;
import org.quartz.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.HashSet;
import java.util.Set;

/**
 * 定时任务管理
 *
 * @author liangb
 */
@Service
public class SchedulerManager implements ApplicationContextAware {


    private Logger logger = LoggerFactory.getLogger(SchedulerManager.class);

    private ApplicationContext applicationContext;

    @Autowired
    private SchedulerFactoryBean schedulerFactoryBean;

    @Autowired
    private IScheduleJobService scheduleJobService;

    public void initDBJob() {
        PolicyUtil.SCHEDULE_JOB_LIST = scheduleJobService.selectUnDeleteList();
        if (!CollectionUtils.isEmpty(PolicyUtil.SCHEDULE_JOB_LIST)) {
            Scheduler scheduler = schedulerFactoryBean.getScheduler();
            for (ScheduleJob job : PolicyUtil.SCHEDULE_JOB_LIST) {
                try {
                    //加载暂停和正常的任务
                    if (!UTSConstants.JOB_STATUS_DELETE.equals(job.getJobStatus())) {
                        JobDetail jobDetail = createJobDetail(job);
                        Trigger trigger = createTrigger(job);
                        scheduler.scheduleJob(jobDetail, trigger);
                        if (UTSConstants.JOB_STATUS_PAUSE.equals(job.getJobStatus())) {   //暂停的任务
                            JobKey jobKey = JobKey.jobKey(job.getJobName(), job.getJobGroup());
                            scheduler.pauseJob(jobKey);
                        }
                    }
                } catch (SchedulerException e) {
                    logger.error("初始化任务出错：job信息" + job, e);
                }
            }
        }
    }

    /**
     * 新增一个定时任务，校验前置，此处不做参数校验
     *
     * @param job
     * @throws SchedulerException
     */
    public void addJob(ScheduleJob job) throws SchedulerException {
        Scheduler scheduler = schedulerFactoryBean.getScheduler();
        JobDetail jobDetail = createJobDetail(job);
        Trigger trigger = createTrigger(job);
        scheduler.scheduleJob(jobDetail, trigger);
        if (UTSConstants.JOB_STATUS_PAUSE.equals(job.getJobStatus())) {   //暂停的任务
            JobKey jobKey = JobKey.jobKey(job.getJobName(), job.getJobGroup());
            scheduler.pauseJob(jobKey);
        }
    }

    /**
     * 更新定时任务触发规则
     *
     * @param job
     */
    public int updateJob(ScheduleJob job) throws SchedulerException {
        Scheduler scheduler = schedulerFactoryBean.getScheduler();
        JobKey jobKey = JobKey.jobKey(job.getJobName(), job.getJobGroup());
        Trigger newTrigger = createTrigger(job);
        JobDetail jobDetail = scheduler.getJobDetail(jobKey);
        Set<Trigger> trigger = new HashSet<Trigger>();
        trigger.add(newTrigger);
        scheduler.scheduleJob(jobDetail, trigger, true);
        if (UTSConstants.JOB_STATUS_PAUSE.equals(job.getJobStatus())) {
            scheduler.pauseJob(jobKey);
        }
        return 1;
    }

    /**
     * 暂停定时任务，正在执行的任务将继续，后续将不再触发该任务
     *
     * @param job
     */
    public void pauseJob(ScheduleJob job) throws SchedulerException {
        Scheduler scheduler = schedulerFactoryBean.getScheduler();
        JobKey jobKey = JobKey.jobKey(job.getJobName(), job.getJobGroup());
        scheduler.pauseJob(jobKey);
    }

    /**
     * 恢复定时任务的触发
     *
     * @param job
     */
    public void resumeJob(ScheduleJob job) throws SchedulerException {
        Scheduler scheduler = schedulerFactoryBean.getScheduler();
        JobKey jobKey = JobKey.jobKey(job.getJobName(), job.getJobGroup());
        scheduler.resumeJob(jobKey);
    }

    /**
     * 删除一个定时任务
     *
     * @param job
     */
    public void deleteJob(ScheduleJob job) throws SchedulerException {
        Scheduler scheduler = schedulerFactoryBean.getScheduler();
        JobKey jobKey = JobKey.jobKey(job.getJobName(), job.getJobGroup());
        scheduler.deleteJob(jobKey);
    }

    /**
     * 触发一次任务执行
     *
     * @param job
     */
    public void triggerJob(ScheduleJob job) throws Exception {
        Scheduler scheduler = schedulerFactoryBean.getScheduler();
        JobKey jobKey = JobKey.jobKey(job.getJobName(), job.getJobGroup());
        scheduler.triggerJob(jobKey);
    }

    /**
     * 根据 ScheduleJob 创建对应的 JobDetail
     *
     * @param job
     * @return
     */
    private JobDetail createJobDetail(ScheduleJob job) {
        JobDetail jobDetail = JobBuilder.newJob(RscJob.class).withIdentity(job.getJobName(), job.getJobGroup()).build();
        jobDetail.getJobDataMap().put(UTSConstants.SCHEDULE_JOB, job);
        jobDetail.getJobDataMap().put(UTSConstants.APP_CONTEXT, applicationContext);
        return jobDetail;
    }

    /**
     * 根据 ScheduleJob 创建对应的触发器
     *
     * @param job
     * @return
     */
    private Trigger createTrigger(ScheduleJob job) {
        CronScheduleBuilder scheduleBuilder = null;
        try {
            // 表达式调度构建器
            scheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression()).withMisfireHandlingInstructionDoNothing();
        } catch (RuntimeException e) {
            throw e;
        }
        // 按新的cronExpression表达式构建一个新的trigger
        Trigger trigger = TriggerBuilder.newTrigger().withIdentity(job.getJobName(), job.getJobGroup()).withSchedule(scheduleBuilder).build();
        return trigger;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    /*
    检查一个任务是否存在
     */
    public boolean checkExists(String jobName, String jobGroup) {
        Scheduler scheduler = schedulerFactoryBean.getScheduler();
        try {
            return scheduler.checkExists(new JobKey(jobName, jobGroup));
        } catch (Exception e) {
            logger.error("验证错误:" + e);
        }

        return true;
    }
}
